#ifndef __EAT_H
#define __EAT_H

#include "stdint.h"

#define EAT_MAX_ADDR_LEN        (4)
#define EAT_MAX_FIELD_LEN       (16)
#define EAT_MAX_VALUES_NUM      (4)
#define EAT_MAX_STR_VAL_LEN     (16)
#define EAT_MAX_BUFFER_LEN      (16)
#define EAT_QUEUE_LEN           (8)

// the types which atcmd can be
enum ATCmdType {
    EAT_CMD_TYPE_TEST = 0,
    EAT_CMD_TYPE_SET,
    EAT_CMD_TYPE_GET,
    EAT_CMD_TYPE_EXEC
};

// the types which ATCmdValue_t can be
enum ATCmdValueType {
    EAT_VALUE_TYPE_NUMBER,
    EAT_VALUE_TYPE_STRING
};

// Enhanced ATCmd Parser status
typedef enum EAT_Status {
    EAT_NO = 0,
    EAT_YES,
    EAT_OK,
    EAT_QUEUE_EMPTY,
} EAT_Status;

typedef struct ATCmdValue_t {
    // type of value
    enum ATCmdValueType type;

    // value
    union {
        float number;
        struct {
            uint8_t str_len;    // length of string
            uint8_t str[EAT_MAX_STR_VAL_LEN];
        } string;
    } value;
} ATCmdValue_t;

typedef struct ATCmd_t {
    // type of atcmd
    enum ATCmdType type;

    // the target address of atcmd
    uint8_t addr_len;
    uint8_t addr[EAT_MAX_ADDR_LEN];

    // the target field of atcmd
    uint8_t field_len;
    uint8_t field_name[EAT_MAX_FIELD_LEN];
    uint8_t field_is_array;
    size_t field_index;

    // value of atcmd
    uint8_t values_num;
    ATCmdValue_t values[EAT_MAX_VALUES_NUM];
} ATCmd_t;


// This is a circle queue
typedef struct ATCmdQueue_t {
    ATCmd_t queue[EAT_QUEUE_LEN];
    uint8_t head;
    uint8_t tail;
    uint8_t size;
} ATCmdQueue_t;

/**
 * Define the struct EAT_t, which is the core of this library.
 * It contains state machine、buffer.
 */
typedef struct EAT_t {
    uint8_t input_queue[EAT_MAX_BUFFER_LEN];
    ATCmdQueue_t output_queue;
    ATCmdQueue_t relay_queue;

    struct {
        uint8_t cur_state;
    } state_machine;
} EAT_t;

EAT_Status EAT_IsQueueEmpty(ATCmdQueue_t *queue);
EAT_Status EAT_IsQueueFull(ATCmdQueue_t *queue);
EAT_Status EAT_PushQueue(ATCmdQueue_t *queue, ATCmd_t atcmd);
EAT_Status EAT_PopQueue(ATCmdQueue_t *queue, ATCmd_t* cmd);

#endif